﻿using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using System;

namespace SingleBlog.Core.Services
{
    using SettingModels;
    using Data;
    using Resources;

    /// <summary>
    /// 表示系统设置的服务。
    /// </summary>
    public class SettingService
    {
        private SingleBlogDbContext _context;
        private IMemoryCache _cache;
        /// <summary>
        /// Initializes a new instance of the <see cref="SettingService"/> class.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="cache">The cache.</param>
        public SettingService(SingleBlogDbContext context, IMemoryCache cache)
        {
            _context = context;
            _cache = cache;
        }

        /// <summary>
        /// 获取指定的设置模型。自动进行反序列化。
        /// </summary>
        /// <typeparam name="TModel">模型的类型。</typeparam>
        /// <returns></returns>
        internal TModel GetSetting<TModel>() where TModel:ISettingModel
        {
            var model = Activator.CreateInstance<TModel>();
            var cacheKey = Setting.CacheKey(model.Key);

            var config = _cache.GetOrCreate(cacheKey, entry =>
            {
                var setting = _context.Settings.Find(model.Key);
                if (setting == null)
                {
                    throw new InvalidOperationException(Language.SettingLoadError);
                }

                return JsonConvert.DeserializeObject<TModel>(setting.Configuration);
            });
            return config;
        }

        /// <summary>
        /// 保存指定的配置模型。会自动序列化该模型成 json 字符串。
        /// </summary>
        /// <typeparam name="TModel">模型的类型。</typeparam>
        /// <param name="settingModel">要保存的模型对象。</param>
        /// <exception cref="ArgumentNullException">settingModel 是 null。</exception>
        public void SaveSetting<TModel>(TModel settingModel) 
            where TModel:ISettingModel
        {
            if (settingModel == null)
            {
                throw new ArgumentNullException(nameof(settingModel));
            }

            var settingStr = JsonConvert.SerializeObject(settingModel);
            var setting = _context.Settings.Find(settingModel.Key);
            if (setting == null)
            {
                _context.Settings.Add(new Setting
                {
                    Key = settingModel.Key,
                    Configuration = settingStr
                });
            }
            else
            {
                setting.Configuration = settingStr;
            }
            _context.SaveChanges();

            _cache.Remove(Setting.CacheKey(settingModel.Key));
        }

        /// <summary>
        /// 获取常规设置。
        /// </summary>
        /// <returns></returns>
        public GeneralSettingModel GetGeneralSetting() => GetSetting<GeneralSettingModel>();
        /// <summary>
        /// 获取系统设置。
        /// </summary>
        /// <returns></returns>
        public SingleBlogInfoSettingModel GetSystemSetting() => GetSetting<SingleBlogInfoSettingModel>();

        /// <summary>
        /// 获取 SMTP 的配置。
        /// </summary>
        /// <returns></returns>
        public SmtpSettingModel GetSmtpSetting() => GetSetting<SmtpSettingModel>();
    }
}
